# -*- coding: utf-8 -*-
# run.py - 主启动脚本
#!/usr/bin/env python3
"""
CodeBuddy Craft 启动脚本
支持后端API服务和前端Streamlit应用的启动
"""

import os
import sys
import subprocess
import argparse
import signal
import time
from pathlib import Path
from typing import Optional

# 添加项目根目录到系统路径
PROJECT_ROOT = Path(__file__).parent
sys.path.insert(0, str(PROJECT_ROOT))


class CodeBuddyLauncher:
    """CodeBuddy Craft 启动器"""
    
    def __init__(self):
        self.backend_process: Optional[subprocess.Popen] = None
        self.frontend_process: Optional[subprocess.Popen] = None
        self.setup_signal_handlers()
    
    def setup_signal_handlers(self):
        """设置信号处理器"""
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
    
    def signal_handler(self, signum, frame):
        """信号处理函数"""
        print(f"\n🛑 接收到信号 {signum}，正在关闭服务...")
        self.stop_all()
        sys.exit(0)
    
    def check_dependencies(self):
        """检查依赖"""
        print("🔍 检查依赖...")
        
        required_packages = [
            "fastapi", "uvicorn", "streamlit", "sqlalchemy", 
            "pydantic", "langchain", "openai"
        ]
        
        missing_packages = []
        
        for package in required_packages:
            try:
                __import__(package)
                print(f"  ✅ {package}")
            except ImportError:
                missing_packages.append(package)
                print(f"  ❌ {package}")
        
        if missing_packages:
            print(f"\n⚠️  缺少以下依赖包: {', '.join(missing_packages)}")
            print("请运行: pip install -r requirements.txt")
            return False
        
        return True
    
    def setup_environment(self):
        """设置环境"""
        print("⚙️  设置环境...")
        
        # 创建必要的目录
        directories = [
            "logs",
            "uploads",
            "temp",
            "data",
            "exports"
        ]
        
        for directory in directories:
            dir_path = PROJECT_ROOT / directory
            dir_path.mkdir(exist_ok=True)
            print(f"  📁 {directory}/")
        
        # 检查环境变量文件
        env_file = PROJECT_ROOT / ".env"
        if not env_file.exists():
            print("  📝 创建默认环境配置文件...")
            self.create_default_env_file(env_file)
        
        # 初始化数据库
        # self.init_database()
    
    def create_default_env_file(self, env_file: Path):
        """创建默认环境配置文件"""
        default_env = '''# CodeBuddy Craft 环境配置
APP_NAME=CodeBuddy Craft
APP_VERSION=1.0.0
DEBUG=true

# 数据库配置
DATABASE_URL=sqlite:///./data/codebuddy.db

# OpenAI配置 - 请填入您的API密钥
OPENAI_API_KEY=your-openai-api-key-here
OPENAI_MODEL=gpt-4

# JWT配置
JWT_SECRET_KEY=change-this-in-production-super-secret-key
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=1440

# 文件上传配置
UPLOAD_DIR=./uploads
MAX_FILE_SIZE=10485760

# 日志配置
LOG_LEVEL=INFO
LOG_FILE=./logs/app.log

# CORS配置
CORS_ORIGINS=["http://localhost:3000","http://localhost:8501"]
'''
        env_file.write_text(default_env, encoding='utf-8')
        print(f"  ✅ 环境配置文件已创建: {env_file}")
        print(f"  ⚠️  请编辑 {env_file} 并填入您的 OpenAI API 密钥")
    
    def init_database(self):
        """初始化数据库"""
        print("  🗄️  初始化数据库...")
        
        try:
            from backend.core.database import init_db
            init_db()
            print("  ✅ 数据库初始化完成")
        except Exception as e:
            print(f"  ❌ 数据库初始化失败: {e}")
    
    def start_backend(self, host: str = "0.0.0.0", port: int = 8000):
        """启动后端API服务"""
        print(f"🚀 启动后端服务 (http://{host}:{port})...")
        
        cmd = [
            sys.executable, "-m", "uvicorn",
            "backend.main:app",
            "--host", host,
            "--port", str(port),
            "--reload"
        ]
        
        try:
            self.backend_process = subprocess.Popen(
                cmd,
                cwd=PROJECT_ROOT,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True,
                bufsize=1
            )
            
            # 等待服务启动
            time.sleep(3)
            
            if self.backend_process.poll() is None:
                print("  ✅ 后端服务启动成功")
                return True
            else:
                print("  ❌ 后端服务启动失败")
                return False
        
        except Exception as e:
            print(f"  ❌ 后端服务启动异常: {e}")
            return False
    
    def start_frontend(self, port: int = 8501):
        """启动前端Streamlit应用"""
        print(f"🎨 启动前端应用 (http://localhost:{port})...")
        
        cmd = [
            sys.executable, "-m", "streamlit", "run",
            "frontend/app.py",
            "--server.port", str(port),
            "--server.address", "localhost",
            "--server.headless", "true",
            "--browser.gatherUsageStats", "false"
        ]
        
        try:
            self.frontend_process = subprocess.Popen(
                cmd,
                cwd=PROJECT_ROOT,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True,
                bufsize=1
            )
            
            # 等待服务启动
            time.sleep(5)
            
            if self.frontend_process.poll() is None:
                print("  ✅ 前端应用启动成功")
                return True
            else:
                print("  ❌ 前端应用启动失败")
                return False
        
        except Exception as e:
            print(f"  ❌ 前端应用启动异常: {e}")
            return False
    
    def start_all(self, backend_port: int = 8000, frontend_port: int = 8501):
        """启动所有服务"""
        print("🎯 启动 CodeBuddy Craft...")
        print("=" * 50)
        
        # 检查依赖和环境
        if not self.check_dependencies():
            return False
        
        self.setup_environment()
        
        # 启动后端服务
        if not self.start_backend(port=backend_port):
            return False
        
        # 启动前端应用
        if not self.start_frontend(port=frontend_port):
            self.stop_backend()
            return False
        
        print("=" * 50)
        print("🎉 CodeBuddy Craft 启动完成！")
        print()
        print(f"📡 后端API地址: http://localhost:{backend_port}")
        print(f"🌐 前端应用地址: http://localhost:{frontend_port}")
        print(f"📚 API文档地址: http://localhost:{backend_port}/docs")
        print()
        print("💡 提示:")
        print("  - 确保已在 .env 文件中配置 OpenAI API 密钥")
        print("  - 按 Ctrl+C 停止所有服务")
        print("=" * 50)
        
        return True
    
    def stop_backend(self):
        """停止后端服务"""
        if self.backend_process:
            print("🛑 停止后端服务...")
            self.backend_process.terminate()
            try:
                self.backend_process.wait(timeout=10)
                print("  ✅ 后端服务已停止")
            except subprocess.TimeoutExpired:
                self.backend_process.kill()
                print("  ⚠️  强制停止后端服务")
            self.backend_process = None
    
    def stop_frontend(self):
        """停止前端应用"""
        if self.frontend_process:
            print("🛑 停止前端应用...")
            self.frontend_process.terminate()
            try:
                self.frontend_process.wait(timeout=10)
                print("  ✅ 前端应用已停止")
            except subprocess.TimeoutExpired:
                self.frontend_process.kill()
                print("  ⚠️  强制停止前端应用")
            self.frontend_process = None
    
    def stop_all(self):
        """停止所有服务"""
        self.stop_frontend()
        self.stop_backend()
        print("✅ 所有服务已停止")
    
    def wait_for_services(self):
        """等待服务运行"""
        try:
            while True:
                # 检查进程状态
                if self.backend_process and self.backend_process.poll() is not None:
                    print("❌ 后端服务意外停止")
                    break
                
                if self.frontend_process and self.frontend_process.poll() is not None:
                    print("❌ 前端应用意外停止")
                    break
                
                time.sleep(1)
        
        except KeyboardInterrupt:
            pass
        
        finally:
            self.stop_all()


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="CodeBuddy Craft - 智能编程助手",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  python run.py                    # 启动完整应用
  python run.py --backend-only     # 仅启动后端服务
  python run.py --frontend-only    # 仅启动前端应用
  python run.py --backend-port 9000 --frontend-port 9001  # 自定义端口
        """
    )
    
    parser.add_argument(
        "--backend-port",
        type=int,
        default=8000,
        help="后端服务端口 (默认: 8000)"
    )
    
    parser.add_argument(
        "--frontend-port", 
        type=int,
        default=8501,
        help="前端应用端口 (默认: 8501)"
    )
    
    parser.add_argument(
        "--backend-only",
        action="store_true",
        help="仅启动后端服务"
    )
    
    parser.add_argument(
        "--frontend-only",
        action="store_true", 
        help="仅启动前端应用"
    )
    
    args = parser.parse_args()
    
    launcher = CodeBuddyLauncher()
    
    try:
        if args.backend_only:
            if launcher.check_dependencies():
                launcher.setup_environment()
                if launcher.start_backend(port=args.backend_port):
                    print("按 Ctrl+C 停止服务")
                    launcher.wait_for_services()
        
        elif args.frontend_only:
            if launcher.check_dependencies():
                if launcher.start_frontend(port=args.frontend_port):
                    print("按 Ctrl+C 停止应用")
                    launcher.wait_for_services()
        
        else:
            if launcher.start_all(
                backend_port=args.backend_port,
                frontend_port=args.frontend_port
            ):
                launcher.wait_for_services()
    
    except Exception as e:
        print(f"❌ 启动失败: {e}")
        launcher.stop_all()
        sys.exit(1)


if __name__ == "__main__":
    main()
